package com.bcx.wind.workflow.errorcontext;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;

import static com.bcx.wind.workflow.parser.ParserConstant.*;

/**
 * 流程定义构建错误信息
 *
 * @author zhanglei
 */
public class ProcessBuilderError implements ProcessErrorContext {

    /**
     * 流程定义xml
     */
    private String  content;

    /**
     * 错误行数
     */
    private int errorLine;

    /**
     * 错误信息
     */
    private  String  errorMsg;


    /**
     * 错误xml内容
     */
    private  String  errorContent;

    /**
     * 错误xml显示html
     */
    private String  errorHtml;

    /**
     * 错误代码
     */
    private int  code = 0;

    /**
     * xml中出现错误的部分内容，在排错时使用
     */
    String[] errorValue;

    /**
     * 错误
     */
    private Throwable throwable;

    @Override
    public String content() {
        return this.content;
    }

    @Override
    public ProcessErrorContext content(String content) {
        this.content = content;
        initErrorXml();
        return this;
    }

    @Override
    public int errorLine() {
        return this.errorLine;
    }

    @Override
    public ProcessErrorContext errorLine(int errorLine) {
        this.errorLine = errorLine;
        initErrorXml();
        return this;
    }

    @Override
    public String errorContent() {
        return this.errorContent;
    }

    @Override
    public ProcessErrorContext errorContent(String errorContent) {
        this.errorContent = errorContent;
        return this;
    }

    @Override
    public String errorHtml() {
        return this.errorHtml;
    }

    @Override
    public ProcessErrorContext errorHtml(String errorHtml) {
        this.errorHtml = errorHtml;
        return this;
    }

    @Override
    public String[] errorValue() {
        return this.errorValue;
    }

    @Override
    public ProcessErrorContext errorValue(String[] values) {
        this.errorValue = values;
        return this;
    }

    public ProcessBuilderError(){

    }

    public ProcessBuilderError(int code, String errorMsg){
        this.code = code;
        this.errorMsg = errorMsg;
    }

    public ProcessBuilderError setContent(String content) {
        this.content = content;
        initErrorXml();
        return this;
    }

    public ProcessBuilderError setErrorLine(int errorLine) {
        this.errorLine = errorLine;
        initErrorXml();
        return this;
    }

    public ProcessBuilderError setErrorContent(String errorContent) {
        this.errorContent = errorContent;
        return this;
    }

    public ProcessBuilderError setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
        return this;
    }

    private void initErrorXml(){
        initErrorContent();
    }

    public boolean  isError(){
        return this.code != 0;
    }

    public ProcessBuilderError setCode(int code){
        this.code = code;
        return this;
    }

    public ProcessBuilderError setErrorValue(String[] errorValue) {
        this.errorValue = errorValue;
        return this;
    }

    /**
     * 构造错误内容
     */
    private void initErrorContent(){
        if(this.content != null && this.errorLine != 0){
            StringBuilder html = new StringBuilder();
            StringReader reader = new StringReader(this.content);
            BufferedReader buf = new BufferedReader(reader);
            int number = 0;
            String errorTxt = "";
            try {
                while (true) {
                    number++;
                    try {
                        errorTxt = buf.readLine();
                        if (errorTxt == null) {
                            break;
                        }

                        if (number == this.errorLine) {
                            this.errorContent = errorTxt;
                            errorTxt = errorTxt.replaceAll(XML_HEAD,LT);
                            errorTxt = errorTxt.replaceAll(XML_TAIL,GT);
                            html.append(RED_P_HTM)
                                    .append(errorTxt)
                                    .append(P_HTML_)
                                    .append(System.lineSeparator());

                        } else if (NULL_STR.equals(errorTxt.trim())) {
                            html.append(System.lineSeparator());
                        } else {
                            errorTxt = errorTxt.replaceAll(XML_HEAD,LT);
                            errorTxt = errorTxt.replaceAll(XML_TAIL,GT);
                            html.append(P_HTM)
                                    .append(errorTxt)
                                    .append(P_HTML_)
                                    .append(System.lineSeparator());
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }finally {
                reader.close();
                try {
                    buf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            this.errorHtml = html.toString();
        }
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return new ProcessBuilderError()
                .setContent(this.content)
                .setErrorContent(this.errorContent)
                .setErrorMsg(this.errorMsg)
                .setErrorLine(this.errorLine);
    }
}
